/*
 * marker.h
 *
 *  Created on: Jul 28, 2010
 *      Author: Pierre Lindenbaum PhD
 *              plindenbaum@yahoo.fr
 *              http://plindenbaum.blogspot.com
 *              
 */
#ifndef TRANS_LOCUS_H
#define TRANS_LOCUS_H
#include <iostream>
#include <stdint.h>
#include "chromosome.h"


class Locus
    {
    private:
	    const ChromosomePtr _chrom;
	    int64_t _position;
	    double _combined;
	    double _genetic;
    public:
	    Locus(
		    const ChromosomePtr chrom,
		    int64_t position,
		    double combined,
		    double genetic
		    ):_chrom(chrom),_position(position),
		    _combined(combined),_genetic(genetic)
		{

		}

	    Locus(const Locus& cp):_chrom(cp._chrom),_position(cp._position),
	    		    _combined(cp._combined),_genetic(cp._genetic)
		{

		}


    const ChromosomePtr chrom() const
	{
        return _chrom;
	}


    int64_t position() const
	{
        return _position;
	}

    double combined() const
	{
	return _combined;
	}

    double genetic() const
    	{
    	return _genetic;
    	}

    friend std::ostream& operator << (std::ostream& out,const Locus& o);


    };

 std::ostream& operator << (std::ostream& out,const Locus& o)
    {
     out << *(o.chrom())<<":" << o.position() << " " << o.combined()<< " " << o.genetic();
    return out;
    }

typedef Locus* LocusPtr;

class LocusList
    {
    protected:
	ChromosomePtr _chrom;
	std::vector<Locus> loci;

	LocusList(const ChromosomePtr chrom):_chrom(chrom)
	    {

	    }
    public:
	typedef int size_type;
	virtual ~LocusList()
	    {

	    }

	size_type lower_bound(size_type first,int64_t position)
	    {
	    size_type len = loci.size() - first;
	    while (len > 0)
	            {
	            int half = len / 2;
	            int middle = first + half;
	            const Locus& x= loci.at(middle);
	            if (x.position()<position)
	                    {
	                    first = middle + 1;
	                    len -= half + 1;
	                    }
	            else
	                    {
	                    len = half;
	                    }
	            }
	    return first;
	    }

	size_type lower_bound(int64_t _position)
	    {
	    return lower_bound(0,position);
	    }

	const ChromosomePtr chrom() const
	    {
	    return _chrom;
	    }

	size_type size() const
	    {
	    return (size_type)loci.size();
	    }

	const LocusPtr at(size_type i) const
	    {
	    return loci.at((std::vector<Locus>::size_type)i);
	    }

	const LocusPtr operator[](size_type i) const
	    {
	    return at(i);
	    }

    };

typedef LocusList* LocusListPtr;
#endif
